package algotradingfx.strategies;

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import algotradingfx.utils.Constants;
import algotradingfx.utils.FXAsset;
import atp.client.trading.methods.TradingMethod.Side;
import atp.client.trading.methods.TradingMethod.Type;
import atp.client.trading.strategies.StrategyPush;
import atp.commons.util.StrategyInfo;
import atp.commons.util.Tick;

public class TriangleArbitrage extends StrategyPush {
	public static Logger LOGGER = Logger.getLogger(TriangleArbitrage.class);

	private static final long serialVersionUID = 1728280496562117242L;

	private static final String STRATEGY_NAME = "TriangleArbitrage";

	private Map<FXAsset, Tick> tickMap;

	public TriangleArbitrage(String ssID, String password) {
		super(new StrategyInfo(STRATEGY_NAME), ssID, password);
	}

	@Override
	public void initialise() {
		declare(FXAsset.EURUSD.toString(), Constants.MOCK_BROKER);
		declare(FXAsset.EURCHF.toString(), Constants.MOCK_BROKER);
		declare(FXAsset.EURJPY.toString(), Constants.MOCK_BROKER);
		declare(FXAsset.USDCHF.toString(), Constants.MOCK_BROKER);
		declare(FXAsset.USDJPY.toString(), Constants.MOCK_BROKER);

		tickMap = new HashMap<FXAsset, Tick>();
		tickMap.put(FXAsset.EURUSD, new Tick());
		tickMap.put(FXAsset.EURCHF, new Tick());
		tickMap.put(FXAsset.EURJPY, new Tick());
		tickMap.put(FXAsset.USDCHF, new Tick());
		tickMap.put(FXAsset.USDJPY, new Tick());
	}

	// CAD/USD * AUD/USD > AUD/USD -> BUY and vice versa
	// EUR/USD * USD/CHF > EUR/CHF
	// EUR/USD * USD/JPY > EUR/JPY
	private double checkArbitrageOpp(Tick t1, Tick t2, Tick t3) {
		final double diff = t1.getAsk() * t2.getAsk() - t3.getAsk();
		if (diff > 0) {
			forex.send(t1.getSymbol(), Type.MARKET, Side.BUY, 1000000, 0.0,
					0.0, Constants.MOCK_BROKER);
			forex.send(t2.getSymbol(), Type.MARKET, Side.BUY, 1000000, 0.0,
					0.0, Constants.MOCK_BROKER);
			forex.send(t3.getSymbol(), Type.MARKET, Side.BUY, 1000000, 0.0,
					0.0, Constants.MOCK_BROKER);
		} else if (diff < 0) {
			forex.send(t1.getSymbol(), Type.MARKET, Side.SELL, 1000000, 0.0,
					0.0, Constants.MOCK_BROKER);
			forex.send(t2.getSymbol(), Type.MARKET, Side.SELL, 1000000, 0.0,
					0.0, Constants.MOCK_BROKER);
			forex.send(t3.getSymbol(), Type.MARKET, Side.SELL, 1000000, 0.0,
					0.0, Constants.MOCK_BROKER);
		}
		return diff;
	}


	@Override
	public boolean run(Object o) {
		if (o instanceof Tick) {
			Tick t = (Tick) o;
			FXAsset asset = FXAsset.valueOf(t.getSymbol());
			tickMap.put(asset, t);
			checkArbitrageOpp(tickMap.get(FXAsset.EURUSD), tickMap
					.get(FXAsset.USDJPY), tickMap.get(FXAsset.EURJPY));
			checkArbitrageOpp(tickMap.get(FXAsset.EURUSD), tickMap
					.get(FXAsset.USDCHF), tickMap.get(FXAsset.EURCHF));
			}
			//but how to close?
		return false;
	}
}
